package game.data;

import echo.math.Vector2;
import echo.Body;
import game.data.ProjectRoleData.AssetsFile;
import game.event.*;
import hx.geom.Point;
import hx.assets.Assets;
import hx.events.Keyboard;
import haxe.Json;
import game.worlds.RoleAction;

using Reflect;

/**
 * 幻想纹章2的人物数据包读取支持
 */
class Hxwz2RolePackageData implements IRoleData {
	/**
	 * 事件Tag
	 */
	public var eventTag:String;

	public var atlas:Array<String> = [];

	/**
	 * 精灵图偏移X
	 */
	public var offestX:Float = 0;

	/**
	 * 精灵图偏移Y
	 */
	public var offestY:Float = 0;

	/**
	 * 编辑器版本号
	 */
	public var editerVersion:String;

	/**
	 * 构建版本号
	 */
	public var buildVersion:String;

	public var offestConfig:Dynamic<{
		x:Float,
		y:Float
	}> = {};

	/**
	 * 动作数据
	 */
	public var actions:Map<String, ActionData> = [];

	/**
	 * 组合键数组，一般是经过了排序，由长组合键到短组合键
	 */
	public var groupKeyActions:Array<ActionData> = [];

	/**
	 * 角色属性数据
	 */
	public var attrData:RoleAttrData = new RoleAttrData();

	/**
	 * 扩展数据
	 */
	public var data:Dynamic = {};

	public function new(xml:Xml) {
		var data:Xml = xml.firstElement();
		if (data.exists("px")) {
			offestX = Std.parseFloat(data.get("px"));
		}
		if (data.exists("py")) {
			offestY = Std.parseFloat(data.get("py"));
		}
		this.offestConfig = {
			content: {
				x: offestX,
				y: offestY
			}
		}
		if (data.exists("eventTag")) {
			eventTag = data.get("eventTag");
		}
		this.atlas.push("content");
		// 解析动作数据
		for (action in data.elements()) {
			if (action.nodeName == "act") {
				var actionData = new ActionData();
				// CD
				actionData.cd = Std.parseInt(action.get("cd"));
				// 技能名称
				actionData.name = action.get("name");
				// 描述
				actionData.desc = action.get("tips");
				// 释放消耗
				actionData.mpConsume = Std.parseInt(action.get("mp"));
				// 生命消耗
				actionData.hpConsume = Std.parseInt(action.get("hp"));
				var groupKeys = [];
				if (actionData.name == "普通攻击" || actionData.name == "空中攻击") {
					groupKeys = [Keyboard.J];
				} else {
					// 组合键
					var leftKey = action.get("left");
					var rightKey = action.get("right");
					if (leftKey != null && leftKey != "无") {
						// 组合键
						for (key in leftKey.split("")) {
							switch key {
								case "↑":
									groupKeys.push(Keyboard.W);
								case "↓":
									groupKeys.push(Keyboard.S);
								case "←":
									groupKeys.push(Keyboard.A);
								case "→":
									groupKeys.push(Keyboard.D);
							}
						}
					}
					if (rightKey != null && rightKey != "无") {
						// 组合键
						groupKeys.push(StringTools.fastCodeAt(rightKey, 0));
					}
				}
				if (groupKeys.length > 0) {
					actionData.groupKeys = groupKeys;
					groupKeyActions.push(actionData);
				}
				// FPS
				var xmlFps = Std.parseInt(action.get("fps"));
				actionData.fps = mathFps(2 + xmlFps);
				// 判断技能类型
				var isAirSkill = action.get("isAirSkill") == "true" || actionData.name == "空中攻击";
				var isIgnoreInjured = action.get("isIgnoreInjured") == "true";
				if (isIgnoreInjured) {
					// 全能技能
					actionData.type = ALL_SKILL;
				} else if (isAirSkill) {
					// 空中技能
					actionData.type = AIR_SKILL;
				} else {
					// 地面技能
					actionData.type = GROUND_SKILL;
				}
				var gox = 0.;
				var goy = 0.;
				// 计算出每帧移动的FPS计算
				var moveFps = xmlFps + 3;
				if (moveFps == 0) {
					moveFps = 1;
				}
				for (frame in action.elements()) {
					var lastFrameData = actionData.frames.length > 0 ? actionData.frames[actionData.frames.length - 1] : null;
					var frameData = new FrameData();
					frameData.eventTag = frame.get("eventTag");
					frameData.name = "content:" + frame.get("name");
					frameData.sound = frame.get("soundName");
					frameData.sound = (frameData.sound == "" || frameData.sound == null) ? null : Assets.formatName(frameData.sound);
					// 计算间隔移动值
					var currentGox = Std.parseFloat(frame.get("gox"));
					var currentGoy = Std.parseFloat(frame.get("goy"));
					if (frame.get("isApplyGoPoint") == "true") {
						frameData.originMoveX = currentGox;
						frameData.originMoveY = currentGoy;
					}
					if (lastFrameData != null) {
						// 需要进行推算长度
						lastFrameData.moveX = (currentGox - gox) / moveFps;
						lastFrameData.moveY = (currentGoy - goy) / moveFps;
					}
					gox = currentGox;
					goy = currentGoy;
					// 计算碰撞块，幻想纹章2只有矩形碰撞块
					if (frame.exists("hitX") && frame.exists("hitY") && frame.exists("hitWidth") && frame.exists("hitHeight")) {
						var hitX = Std.parseFloat(frame.get("hitX"));
						var hitY = Std.parseFloat(frame.get("hitY"));
						var hitWidth = Std.parseFloat(frame.get("hitWidth"));
						var hitHeight = Std.parseFloat(frame.get("hitHeight"));
						frameData.collision = new Body({
							shape: {
								type: POLYGON,
								vertices: [
									new Vector2(hitX, hitY),
									new Vector2(hitX + hitWidth, hitY),
									new Vector2(hitX + hitWidth, hitY + hitHeight),
									new Vector2(hitX, hitY + hitHeight)
								]
							}
						});
						// 碰撞块有效时间
						var hitLiveTime = Std.parseFloat(frame.get("hiteffective")) * 1 / 30;
						frameData.collisionLiveTime = hitLiveTime;
						// 添加击中数据
						frameData.hitData = new HitData();
						frameData.hitData.hitMoveX = Std.parseFloat(frame.get("asZ")) * 0.35;
						frameData.hitData.hitMoveY = Std.parseFloat(frame.get("asY")) * 0.35;
						frameData.hitData.isBlow = frame.get("isBlow") == "blow";
						if (frame.exists("asR"))
							frameData.hitData.stiffenTime = Std.parseFloat(frame.get("asR")) / 60;
						else if (frame.exists("asS")) {
							frameData.hitData.stiffenTime = Std.parseFloat(frame.get("asS")) / 60;
						}
					}
					if (frame.exists("effects")) {
						var effects:Array<Dynamic> = Json.parse(frame.get("effects"));
						if (effects.length > 0) {
							for (value in effects) {
								var effectJson = Json.parse(value);
								// trace(actionData.name, effectJson);
								var effectData:EffectData = new EffectData();
								effectData.x = effectJson.x;
								effectData.y = effectJson.y;
								effectData.rotation = effectJson.rotation;
								effectData.name = effectJson.name;
								effectData.scaleX = effectJson.scaleX;
								effectData.scaleY = effectJson.scaleY;
								effectData.displayName = effectJson.findName;
								effectData.blendMode = effectJson.blendMode;
								effectData.isLockAction = effectJson != null && effectJson.isLockAction;
								effectData.isFollow = effectJson.isFollow != null && effectJson.isFollow;
								// 位移速度
								if (effectJson.gox != 0 || effectJson.goy != 0) {
									effectData.speed = new Point(effectJson.gox * 0.5, effectJson.goy * 0.5);
								}
								effectData.liveTime = (effectJson.time == null || effectJson.time == 0) ? -1 : effectJson.time;
								if (effectJson.color != null) {
									var array:Array<Float> = effectJson.color;
									if (array.length > 0) {
										// effectData.colorMatrixFilter = array;
									}
								}
								if (effectJson.fps != null) {
									effectData.fps = mathFps(effectJson.fps - 1);
								}
								effectData.root = effectJson;
								frameData.addEffect(effectData);
							}
						}
					}
					actionData.addFrame(frameData);
					// TODO 跳跃动作特殊处理，仅保留最后1帧，前面的帧可以作为过渡动画优化
					if (actionData.name == RoleAction.JUMP_UP) {
						actionData.frames = [actionData.frames[actionData.frames.length - 1]];
					} else if (actionData.name == RoleAction.JUMP_ATTACK) {
						// 空中攻击允许位移
						actionData.allowAirMove = true;
					}
					// 停止帧判断
					if (frame.exists("asA")) {
						frameData.isStop = frame.get("asA") == "stop";
						if (frameData.isStop) {
							// trace(actionData.name, "停顿帧");
						}
					}
				}
				if (actionData.frames.length == 0)
					continue;
				this.actions.set(actionData.name, actionData);
				actionData.updateActionData();
			} else if (action.nodeName == "ifRoot") {}
		}
		// 组合键排序
		groupKeyActions.sort(function(a, b) {
			return a.groupKeys.length > b.groupKeys.length ? -1 : 1;
		});
	}

	/**
	 * 反推幻想纹章2的人物包FPS，将FPS反推到60FPS比例中
	 * @param fps 
	 * @return Int
	 */
	private function mathFps(fps:Int):Int {
		// 幻纹2的fps是按30FPS计算的，因此，这里需要合理计算
		// fps++;
		var fpsDt = 1 / 36;
		// 角色的FPS间隔值值默认是2
		var roleFps:Float = fps * fpsDt;
		// 根据FPS间隔反推FPS值
		return roleFps <= 0 ? 36 : Std.int(1 / roleFps);
	}
}
